﻿#region License statement
// NJamb, a specification and delta-specification DSL
// Copyright (c) 2010-2011, Mark Knell
// Published under the MIT License; all other rights reserved
#endregion

#region using...
using System;
using NJamb.NUnit;
using NJamb.Parser.SubjectBuilders;
using NJamb.Parser.Subjects.Singular;
using NJamb.Specifications.Delta;
using NUnit.Framework;
using Stile.Patterns.SelfDescribingPredicates;
using Stile.Testing.SampleTypes;
#endregion

namespace NJamb.Tests.Specifications.Delta
{
	[TestFixture]
	public class SingularDeltaAcceptanceTests : EvaluatingSampleFixture
	{
		[Test]
		public void AndLaterHas()
		{
			// arrange
			int hashCode = _sample.Int.GetHashCode();
			IDeltaSpecification deltaSpecification = Specify.For(() => _sample).That(x => x.Int).Has.HashCode(hashCode) //
				.AndLater.Has.HashCode(hashCode);

			// act
			IPreconditionEvaluation preconditionEvaluation = deltaSpecification.EvaluatePrecondition();

			// assert
			Assert.That(preconditionEvaluation.Evaluation.Success);
			Assert.That(preconditionEvaluation.GetPostcondition().Evaluate().Success);
		}

		[Test]
		public void AndLaterIs()
		{
			const int i = -1;
			Assert.That(i, Is.Not.EqualTo(Sample.Default.Int), "precondition");
			Assert.That(_sample.Int, Is.EqualTo(Sample.Default.Int), "precondition");

			// arrange
			IDeltaSpecification deltaSpecification = Specify.For(() => _sample).That(x => x.Int).Is.EqualTo(Sample.Default.Int) //
				.AndLater.Is.EqualTo(i);

			// act
			IPreconditionEvaluation preconditionEvaluation = deltaSpecification.EvaluatePrecondition();
			IEvaluation before = preconditionEvaluation.Evaluation;
			_sample.Int = i;
			IEvaluation after = preconditionEvaluation.GetPostcondition().Evaluate();

			// assert
			Assert.That(before.Success, Is.True);
			Assert.That(after.Success, Is.True);
		}

		[Test]
		public void WillChange()
		{
			// arrange
			const string initialString = "Nothing changed!";
			_sample.String = initialString;
			IDeltaSpecification deltaSpecification = Specify.For(() => _sample).That(x => x.String).WillChange();

			// act
			IPreconditionEvaluation preconditionEvaluation = deltaSpecification.EvaluatePrecondition();
			IEvaluation before = preconditionEvaluation.Evaluation;
			Assert.That(_sample.String, Is.EqualTo(initialString), "precondition");
			IEvaluation after = preconditionEvaluation.GetPostcondition().Evaluate();

			// assert
			Assert.That(before.Success, Is.True);
			Assert.That(after.Success, Is.False);
			Assert.That(after.Reason,
				Is.EqualTo(string.Format("expected _sample.String would change{0} but was always \"{1}\".", Environment.NewLine, initialString)));
		}

		[Test]
		public void WillChangeTo_DidNotChange()
		{
			// arrange
			const string initialString = "Nothing";
			const string difference = " changed!";
			_sample.String = initialString;
			IDeltaSpecification deltaSpecification = Specify.For(() => _sample).That(x => x.String).WillChangeTo(initialString + difference);

			// act
			IPreconditionEvaluation preconditionEvaluation = deltaSpecification.EvaluatePrecondition();
			IEvaluation before = preconditionEvaluation.Evaluation;
			Assert.That(_sample.String, Is.EqualTo(initialString), "precondition");
			IEvaluation after = preconditionEvaluation.GetPostcondition().Evaluate();

			// assert
			Assert.That(before.Success, Is.True);
			AssertEvaluationFailed(after,
				string.Format("expected _sample.String would change to \"{0}\"{1} but was \"{2}\".",
					initialString + difference,
					Environment.NewLine,
					initialString));
		}

		[Test]
		public void WillNotChange()
		{
			// arrange
			const string initialString = "Nothing";
			const string difference = " changed!";
			_sample.String = initialString;
			IDeltaSpecification deltaSpecification = Specify.For(() => _sample).That(x => x.String).WillNotChange();

			// act
			IPreconditionEvaluation preconditionEvaluation = deltaSpecification.EvaluatePrecondition();
			IEvaluation before = preconditionEvaluation.Evaluation;
			_sample.String = _sample.String + difference;
			Assert.That(_sample.String, Is.Not.EqualTo(initialString), "precondition");
			IEvaluation after = preconditionEvaluation.GetPostcondition().Evaluate();

			// assert
			Assert.That(before.Success, Is.True);
			Assert.That(after.Success, Is.False);
			Assert.That(after.Reason,
				Is.EqualTo(string.Format("expected _sample.String would be \"{0}\"" + Environment.NewLine + " but was \"{0}{1}\".",
					initialString,
					difference)));
		}
	}
}
